﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

using InformationExtraction.Common;
using InformationExtraction.Interface;

namespace InformationExtraction
{
    class FileParser
    {
        private StreamReader reader = null;
        private string content = null;
        private InformationType currentType;
        private TagType tag;

        private TagType CurrentTag
        {
            get
            {
                return tag;
            }
            set
            {
                switch (value)
                {
                    case TagType.AcronymR:
                    case TagType.CRDateR:
                    case TagType.DateR:
                    case TagType.HomePageR:
                    case TagType.LocationR:
                    case TagType.NameR:
                    case TagType.NotificationDateR:
                    case TagType.SubmissionDateR:
                        currentType = InformationType.None;
                        tag = TagType.None;
                        break;
                    case TagType.AcronymL:
                        currentType = InformationType.Acronym;
                        tag = TagType.None;
                        break;
                    case TagType.CRDateL:
                        currentType = InformationType.CRDate;
                        tag = TagType.None;
                        break;
                    case TagType.DateL:
                        currentType = InformationType.Date;
                        tag = TagType.None;
                        break;
                    case TagType.HomePageL:
                        currentType = InformationType.Homepage;
                        tag = TagType.None;
                        break;
                    case TagType.LocationL:
                        currentType = InformationType.Location;
                        tag = TagType.None;
                        break;
                    case TagType.NameL:
                        currentType = InformationType.Name;
                        tag = TagType.None;
                        break;
                    case TagType.NotificationDateL:
                        currentType = InformationType.NotificationDate;
                        tag = TagType.None;
                        break;
                    case TagType.SubmissionDateL:
                        currentType = InformationType.SubmissionDate;
                        tag = TagType.None;
                        break;
                    case TagType.None:
                        tag = TagType.None;
                        break;
                }
            }
        }


        public FileParser()
        { 
        }


        public Document ParseFile(FileInfo f)
        {
            try
            {
                reader = new StreamReader(f.FullName);
                content = reader.ReadToEnd();
                reader.Close();
            }
            catch (IOException ex)
            {
                System.Console.Write(ex.Message);
            }

            return Parse(content);
         
            // Feature Extraction
             
            // Feature File Generation
        }

        private Document Parse(string text)
        {
            Document doc = new Document();
            doc.Content = (string) text.Clone();

            ParseLines(text, doc);
            LinkTokens(doc);

            //ParseSentence(text, ref doc);

            return doc;
        }

        private void ParseLines(string text, Document doc)
        {
            doc.Lines = new List<Line>();

            string[] strLines = text.Split('\n');

            Line line = null;
            int nLine = strLines.Length;
            Regex charRegex = new Regex(@"[a-zA-Z]+");
            Regex keyValueRegex = new Regex(@"[a-zA-Z0-9]+[ ]*:[ ]*[a-zA-Z0-9]+");
            Regex emptyRegex = new Regex(@"^[ ]*$");
            Regex puncEndRegex = new Regex(@"[,.!]+[ ]*$");

            
            for (int l = 0; l < nLine; l++)
            {
                line = new Line();
                line.InDocument = doc;
                line.RawContent = (string) strLines[l].Clone();
                line.No = l;
           
                if (l > 0)
                {
                    doc.Lines[l - 1].NextLine = line;
                    line.PriorLine = doc.Lines[l - 1];
                }
                
                line.IsSeperaterLine = !charRegex.Match(strLines[l]).Success;
                line.IsKeyValue = keyValueRegex.Match(strLines[l]).Success;
                line.IsEmpty = emptyRegex.Match(strLines[l]).Success;
                line.IsEndWithPunctuation = puncEndRegex.Match(strLines[l]).Success;

                doc.Lines.Add(line);

                Tokenize(line, doc);
                line.Content = ReConstructContent(line);
            }
        }

        private string ReConstructContent(Line line)
        {
            string text = "";
            foreach (Token t in line.Tokens)
            {
                text += t.Content + " ";
            }

            return text;
        }

        private void ParseSentence(string text, Document doc)
        {
        }

        private void Tokenize(Line line, Document doc)
        {
            string[] pharses = line.RawContent.Split(' ');

            foreach (string s in pharses)
            {
                ParsePhrase(s, line, doc);                
            }
        }

        private void ParsePhrase(string phrase, Line line, Document doc)
        {
            if (phrase.Equals(" ") || phrase.Equals(""))
                return;

            Token token = null;
            string preRemain = "";
            string postRemain = "";

            TagType type = Tag.MatchTag(phrase, ref preRemain, ref postRemain);

            if (type == TagType.None)
            {
                token = new Token();
                token.Content = (string) phrase.Clone();
                token.Type = currentType;
                token.InLine = line;

                // todo: InSentence
                line.Tokens.Add(token);
            }
            else
            {
                if (preRemain.Length > 0)
                    ParsePhrase(preRemain, line, doc);

                CurrentTag = type;

                if (postRemain.Length > 0)
                    ParsePhrase(postRemain, line, doc);
            }
        }

        private void LinkTokens(Document doc)
        {
            Token lastToken = null;

            foreach (Line currentLine in doc.Lines)
            {
                foreach (Token token in currentLine.Tokens)
                {
                    token.Prior = lastToken;

                    if (lastToken != null)
                        lastToken.Next = token;

                    lastToken = token;
                }
            }
        }


    }
}
